<template>
  <div class="knowledge-graph-container">
    <!-- 顶部工具栏 -->
    <div class="graph-toolbar">
      <div class="toolbar-left">
        <div class="search-container">
          <el-autocomplete
            v-model="searchKeyword"
            :fetch-suggestions="querySearchSuggestions"
            placeholder="搜索作物或品种（如：小麦、保麦）"
            class="search-input"
            @select="handleSuggestionSelect"
            @keyup.enter="handleSearch"
            :debounce="300"
            clearable
          >
            <template #prefix>
              <el-icon><Search /></el-icon>
            </template>
            <template #default="{ item }">
              <div class="suggestion-item">
                <div class="suggestion-main">
                  <span class="suggestion-name">{{ item.name }}</span>
                  <el-tag :type="getSuggestionTagType(item.type)" size="small">
                    {{ getSuggestionTypeLabel(item.type) }}
                  </el-tag>
                </div>
                <div class="suggestion-desc">{{ item.description }}</div>
              </div>
            </template>
          </el-autocomplete>
          <el-button type="primary" @click="handleSearch" :loading="searching">
            搜索
          </el-button>
        </div>
      </div>
      
      <div class="toolbar-right">
        <el-button @click="debugData" type="info" size="small">
          调试数据
        </el-button>
        <el-button @click="reRenderGraph" type="success" size="small">
          重新渲染
        </el-button>
        <el-button type="warning" @click="buildGraph" :loading="building">
          重建图谱数据
        </el-button>
      </div>
    </div>
    
    <!-- 图例和控制面板 -->
    <div class="graph-legend">
      <div class="legend-left">
        <div class="legend-item">
          <div class="legend-dot crop"></div>
          <span>作物</span>
        </div>
        <div class="legend-item">
          <div class="legend-dot variety"></div>
          <span>品种</span>
        </div>
        <div class="legend-item">
          <div class="legend-dot feature"></div>
          <span>特征</span>
        </div>
      </div>
      
      <div class="legend-center">
        <el-radio-group v-model="displayMode" @change="onDisplayModeChange" size="small">
          <el-radio-button label="simple">简化模式</el-radio-button>
          <el-radio-button label="detailed">详细模式</el-radio-button>
        </el-radio-group>
      </div>
      
      <div class="legend-help">
        <span>💡 点击节点查看详情，拖拽节点可调整位置，滚轮缩放视图</span>
      </div>
    </div>
    
    <!-- 主要图谱区域 -->
    <div class="graph-main" v-loading="loading">
      <div id="knowledge-graph" ref="graphContainer"></div>
      
      <!-- 节点信息面板 -->
      <div class="node-info-panel" v-if="selectedNode" :style="panelStyle">
        <div class="panel-header">
          <h4>{{ selectedNode.name }}</h4>
          <el-button text @click="selectedNode = null">
            <span>×</span>
          </el-button>
        </div>
        <div class="panel-content">
          <p><strong>类型:</strong> {{ getNodeTypeLabel(selectedNode.type) }}</p>
          <p v-if="selectedNode.description">
            <strong>描述:</strong> {{ selectedNode.description }}
          </p>
          
          <!-- 操作按钮 -->
          <div class="panel-actions" v-if="selectedNode.type === 'variety'">
            <el-button type="primary" size="small" @click="viewVarietyDetail(selectedNode)">
              查看详情
            </el-button>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 数据展示 -->
    <div style="margin-top: 20px;">
      <el-card>
        <template #header>
          <h3>图谱数据统计</h3>
        </template>
        
        <div class="data-stats">
          <div class="stat-item">
            <span class="stat-label">节点数量：</span>
            <span class="stat-value">{{ graphData.nodes ? graphData.nodes.length : 0 }}</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">关系数量：</span>
            <span class="stat-value">{{ graphData.links ? graphData.links.length : 0 }}</span>
          </div>
          <div class="stat-item" v-if="renderStats.validNodes !== undefined">
            <span class="stat-label">有效节点：</span>
            <span class="stat-value success">{{ renderStats.validNodes }}</span>
          </div>
          <div class="stat-item" v-if="renderStats.validLinks !== undefined">
            <span class="stat-label">有效关系：</span>
            <span class="stat-value success">{{ renderStats.validLinks }}</span>
          </div>
          <div class="stat-item" v-if="renderStats.invalidLinks !== undefined && renderStats.invalidLinks > 0">
            <span class="stat-label">无效关系：</span>
            <span class="stat-value error">{{ renderStats.invalidLinks }}</span>
          </div>
        </div>
        
        <el-divider content-position="left">节点列表（前20个）</el-divider>
        <el-table :data="displayNodes" style="width: 100%" max-height="300">
          <el-table-column prop="id" label="节点ID" width="150" />
          <el-table-column prop="name" label="节点名称" width="150" />
          <el-table-column prop="type" label="节点类型" width="100">
            <template #default="scope">
              <el-tag :type="getTypeTagType(scope.row.type)">
                {{ getNodeTypeLabel(scope.row.type) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="description" label="描述" />
        </el-table>
        
        <div style="margin-top: 10px; text-align: center;" v-if="graphData.nodes && graphData.nodes.length > 20">
          <span style="color: #999; font-size: 12px;">
            显示前20个节点，共{{ graphData.nodes.length }}个节点
          </span>
        </div>
      </el-card>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, computed } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Search } from '@element-plus/icons-vue';
import * as d3 from 'd3';

// 导入API
import { 
  rebuildKnowledgeGraph, 
  getKnowledgeGraphData, 
  searchGraphNodes,
  getSearchSuggestions
} from '@/api/agriculture/guo/knowledge/knowledgeGraph';

console.log('知识图谱页面开始加载...');

// 响应式数据
const searchKeyword = ref('');
const searching = ref(false);
const building = ref(false);
const loading = ref(false);
const graphContainer = ref(null);
const graphData = ref({ nodes: [], links: [] });
const selectedNode = ref(null);
const panelStyle = ref({});
const renderStats = ref({}); // 渲染统计信息
const displayMode = ref('simple'); // 显示模式：simple=只显示作物和品种，detailed=包含特征
const selectedSuggestion = ref(null); // 选中的搜索建议

// D3相关变量
let svg = null;
let simulation = null;

// 计算属性：显示的节点（前20个）
const displayNodes = computed(() => {
  if (!graphData.value.nodes || !Array.isArray(graphData.value.nodes)) {
    console.log('displayNodes: 节点数据无效', graphData.value.nodes);
    return [];
  }
  console.log('displayNodes: 有效节点数据', graphData.value.nodes.length);
  return graphData.value.nodes.slice(0, 20);
});

/**
 * 初始化图谱
 */
const initGraph = async () => {
  loading.value = true;
  try {
    console.log('开始加载图谱数据...');
    await loadGraphData('crop_1');
    console.log('图谱数据加载完成');
  } catch (error) {
    console.error('初始化图谱失败:', error);
    ElMessage.error('初始化图谱失败');
  } finally {
    loading.value = false;
  }
};

/**
 * 加载图谱数据
 */
const loadGraphData = async (centerNode = 'crop_1') => {
  try {
    console.log('请求图谱数据，中心节点:', centerNode);
    const response = await getKnowledgeGraphData(centerNode);
    console.log('获取到的原始数据:', response);
    
    if (response.code === 200) {
      // 检查数据结构
      console.log('数据详情:', {
        nodes: response.data.nodes,
        links: response.data.links,
        nodesLength: response.data.nodes ? response.data.nodes.length : 0,
        linksLength: response.data.links ? response.data.links.length : 0
      });
      
      graphData.value = response.data;
      ElMessage.success(`图谱数据加载成功：${response.data.nodes ? response.data.nodes.length : 0}个节点`);
      
      // 渲染D3图谱
      nextTick(() => {
        console.log('准备渲染图谱，当前数据:', graphData.value);
        renderGraph();
      });
    } else {
      ElMessage.error('获取图谱数据失败：' + response.msg);
    }
  } catch (error) {
    console.error('加载图谱数据失败:', error);
    ElMessage.error('加载图谱数据失败');
    throw error;
  }
};

/**
 * 渲染D3图谱
 */
const renderGraph = () => {
  console.log('开始渲染图谱...');
  console.log('当前图谱数据:', graphData.value);
  
  if (!graphData.value) {
    console.warn('图谱数据为空');
    return;
  }
  
  if (!graphData.value.nodes || graphData.value.nodes.length === 0) {
    console.warn('节点数据为空:', graphData.value.nodes);
    return;
  }
  
  // 数据验证和清理
  const allValidNodes = graphData.value.nodes.filter(node => node && node.id && node.name);
  
  // 根据显示模式过滤节点
  const validNodes = filterNodesByMode(allValidNodes);
  
  console.log(`显示模式: ${displayMode.value}`);
  console.log(`总有效节点: ${allValidNodes.length}, 过滤后节点: ${validNodes.length}`);
  
  // 创建节点ID集合
  const nodeIds = new Set(validNodes.map(n => n.id));
  console.log('节点ID集合大小:', nodeIds.size);
  
  // 过滤有效的连接（source和target都必须存在于节点中）
  let validLinks = [];
  if (graphData.value.links && Array.isArray(graphData.value.links)) {
    validLinks = graphData.value.links.filter(link => {
      const sourceId = typeof link.source === 'string' ? link.source : (link.source?.id || link.source);
      const targetId = typeof link.target === 'string' ? link.target : (link.target?.id || link.target);
      
      const isValid = nodeIds.has(sourceId) && nodeIds.has(targetId);
      if (!isValid) {
        console.log('过滤无效连接:', { source: sourceId, target: targetId });
      }
      return isValid;
    });
  }
  
  console.log(`有效连接数量: ${validLinks.length}/${graphData.value.links ? graphData.value.links.length : 0}`);
  
  if (validNodes.length === 0) {
    console.error('没有有效的节点数据');
    return;
  }

  // 清除旧的SVG
  d3.select('#knowledge-graph').selectAll('*').remove();
  
  const container = document.getElementById('knowledge-graph');
  if (!container) {
    console.error('找不到图谱容器元素');
    return;
  }
  
  const width = container.clientWidth || 800;
  const height = 600;
  console.log('容器尺寸:', { width, height });
  
  // 创建SVG
  svg = d3.select('#knowledge-graph')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .style('border', '1px solid #ccc')
    .call(d3.zoom()
      .scaleExtent([0.1, 4])
      .on('zoom', (event) => {
        g.attr('transform', event.transform);
      }));
  
  console.log('SVG创建完成');
  
  // 创建主要绘图区域
  const g = svg.append('g');
  
  // 处理连接数据，确保格式正确
  const linksData = validLinks.map(link => ({
    source: typeof link.source === 'string' ? link.source : (link.source?.id || link.source),
    target: typeof link.target === 'string' ? link.target : (link.target?.id || link.target),
    type: link.type || '',
    label: link.label || ''
  }));
  
  console.log('处理后的连接数据示例:', linksData.slice(0, 3));
  
  // 创建力导向模拟 - 根据显示模式和节点数量优化参数
  const nodeCount = validNodes.length;
  const isDetailedMode = displayMode.value === 'detailed';
  
  simulation = d3.forceSimulation(validNodes)
    .force('link', d3.forceLink(linksData).id(d => d.id).distance(d => {
      // 根据节点类型和模式调整距离
      if (isDetailedMode) {
        if (d.source.type === 'crop' || d.target.type === 'crop') return 200;
        if (d.source.type === 'variety' || d.target.type === 'variety') return 120;
        return 80;
      } else {
        if (d.source.type === 'crop' || d.target.type === 'crop') return 150;
        return 100;
      }
    }))
    .force('charge', d3.forceManyBody().strength(d => {
      // 根据节点类型和数量调整斥力
      const baseStrength = isDetailedMode ? -600 : -400;
      const nodeCountFactor = Math.min(nodeCount / 50, 2); // 节点越多，斥力越强
      
      if (d.type === 'crop') return baseStrength * 2 * nodeCountFactor;
      if (d.type === 'variety') return baseStrength * 1.5 * nodeCountFactor;
      return baseStrength * nodeCountFactor;
    }))
    .force('center', d3.forceCenter(width / 2, height / 2))
    .force('collision', d3.forceCollide().radius(d => getNodeRadius(d.type) + (isDetailedMode ? 10 : 5)))
    .alpha(0.3)  // 降低初始能量
    .alphaDecay(isDetailedMode ? 0.02 : 0.05)  // 详细模式下更慢的衰减
    .velocityDecay(0.4); // 增加速度衰减，减少震荡
  
  console.log(`力导向模拟创建完成 - 模式: ${displayMode.value}, 节点数: ${nodeCount}`);
  
  // 绘制连线
  const link = g.append('g')
    .attr('class', 'links')
    .selectAll('line')
    .data(linksData)
    .enter().append('line')
    .attr('stroke', '#999')
    .attr('stroke-opacity', 0.6)
    .attr('stroke-width', 2);
  
  console.log('连线创建完成，数量:', linksData.length);
  
  // 绘制节点
  const node = g.append('g')
    .attr('class', 'nodes')
    .selectAll('g')
    .data(validNodes)
    .enter().append('g')
    .attr('class', 'node')
    .call(d3.drag()
      .on('start', dragstarted)
      .on('drag', dragged)
      .on('end', dragended));
  
  console.log('节点组创建完成，数量:', validNodes.length);
  
  // 添加节点圆圈
  node.append('circle')
    .attr('r', d => getNodeRadius(d.type))
    .attr('fill', d => getNodeColor(d.type))
    .attr('stroke', '#fff')
    .attr('stroke-width', 2);
  
  // 添加节点标签
  node.append('text')
    .attr('dy', '0.35em')
    .attr('text-anchor', 'middle')
    .style('font-size', d => getNodeFontSize(d.type))
    .style('font-weight', d => d.type === 'crop' ? 'bold' : 'normal')
    .style('fill', '#333')
    .style('pointer-events', 'none')
    .text(d => {
      const name = d.name || '未知';
      return name.length > 8 ? name.substring(0, 8) + '...' : name;
    });
  
  // 添加事件监听
  node
    .on('click', (event, d) => {
      event.stopPropagation();
      selectNode(d, event);
    })
    .on('dblclick', (event, d) => {
      event.stopPropagation();
      console.log('双击节点:', d);
    });
  
  // 更新模拟
  simulation.on('tick', () => {
    link
      .attr('x1', d => d.source.x || 0)
      .attr('y1', d => d.source.y || 0)
      .attr('x2', d => d.target.x || 0)
      .attr('y2', d => d.target.y || 0);
    
    node.attr('transform', d => `translate(${d.x || 0},${d.y || 0})`);
  });
  
  // 点击空白处取消选择
  svg.on('click', () => {
    selectedNode.value = null;
  });
  
  console.log('D3图谱渲染完成');
  console.log(`最终渲染: ${validNodes.length}个节点, ${linksData.length}个连接`);
  
  // 更新渲染统计信息
  renderStats.value = {
    validNodes: validNodes.length,
    validLinks: linksData.length,
    invalidLinks: (graphData.value.links ? graphData.value.links.length : 0) - linksData.length
  };
  
  // 添加调试信息到页面
  setTimeout(() => {
    console.log('渲染后检查: SVG元素数量', svg.selectAll('*').size());
    console.log('节点元素数量:', svg.selectAll('.node').size());
    console.log('连线元素数量:', svg.selectAll('line').size());
  }, 1000);
};

/**
 * 获取节点半径
 */
const getNodeRadius = (type) => {
  const radiusMap = {
    'crop': 25,
    'variety': 18,
    'feature': 12
  };
  return radiusMap[type] || 15;
};

/**
 * 获取节点颜色
 */
const getNodeColor = (type) => {
  const colorMap = {
    'crop': '#ff7875',      // 红色 - 作物
    'variety': '#40a9ff',   // 蓝色 - 品种
    'feature': '#52c41a'    // 绿色 - 特征
  };
  return colorMap[type] || '#8c8c8c';
};

/**
 * 获取节点字体大小
 */
const getNodeFontSize = (type) => {
  const sizeMap = {
    'crop': '14px',
    'variety': '12px',
    'feature': '10px'
  };
  return sizeMap[type] || '12px';
};

/**
 * 选中节点
 */
const selectNode = (node, event) => {
  selectedNode.value = node;
  console.log('选中节点:', node);
  
  // 计算面板位置
  panelStyle.value = {
    position: 'fixed',
    left: (event.clientX + 10) + 'px',
    top: (event.clientY - 50) + 'px',
    zIndex: 1000
  };
};

/**
 * 获取节点类型标签
 */
const getNodeTypeLabel = (type) => {
  const labelMap = {
    'crop': '作物',
    'variety': '品种', 
    'feature': '特征'
  };
  return labelMap[type] || type;
};

/**
 * 获取标签类型样式
 */
const getTypeTagType = (type) => {
  const typeMap = {
    'crop': 'danger',    // 红色
    'variety': 'primary', // 蓝色
    'feature': 'success'  // 绿色
  };
  return typeMap[type] || '';
};

/**
 * 获取搜索建议
 */
const querySearchSuggestions = async (queryString, callback) => {
  if (!queryString || queryString.length < 1) {
    callback([]);
    return;
  }
  
  try {
    const response = await getSearchSuggestions(queryString);
    if (response.code === 200) {
      callback(response.data || []);
    } else {
      callback([]);
    }
  } catch (error) {
    console.error('获取搜索建议失败:', error);
    callback([]);
  }
};

/**
 * 处理搜索建议选择
 */
const handleSuggestionSelect = (item) => {
  console.log('选择搜索建议:', item);
  selectedSuggestion.value = item;
  searchKeyword.value = item.name;
  
  // 立即执行搜索
  handleSearchWithNode(item.id);
};

/**
 * 使用指定节点ID搜索
 */
const handleSearchWithNode = async (nodeId) => {
  searching.value = true;
  try {
    console.log('使用节点ID搜索:', nodeId);
    const response = await searchGraphNodes(searchKeyword.value, nodeId);
    console.log('搜索结果:', response);
    
    if (response.code === 200 && response.data && response.data.centerNode) {
      await loadGraphData(response.data.centerNode);
      
      const searchType = response.data.searchType || 'crop';
      if (searchType === 'variety') {
        ElMessage.success(`已切换到品种"${searchKeyword.value}"的知识图谱`);
      } else {
        ElMessage.success(`已切换到${searchKeyword.value}的知识图谱`);
      }
    } else {
      ElMessage.warning(response.msg || '搜索失败');
    }
  } catch (error) {
    console.error('搜索失败:', error);
    ElMessage.error('搜索失败');
  } finally {
    searching.value = false;
  }
};

/**
 * 获取建议项标签类型
 */
const getSuggestionTagType = (type) => {
  const typeMap = {
    'crop': 'danger',
    'variety': 'primary',
    'feature': 'success'
  };
  return typeMap[type] || '';
};

/**
 * 获取建议项类型标签
 */
const getSuggestionTypeLabel = (type) => {
  const labelMap = {
    'crop': '作物',
    'variety': '品种',
    'feature': '特征'
  };
  return labelMap[type] || type;
};

/**
 * 显示模式切换
 */
const onDisplayModeChange = (mode) => {
  console.log('切换显示模式:', mode);
  if (graphData.value && graphData.value.nodes && graphData.value.nodes.length > 0) {
    renderGraph();
  }
};

/**
 * 过滤节点（根据显示模式）
 */
const filterNodesByMode = (nodes) => {
  if (displayMode.value === 'simple') {
    // 简化模式：只显示作物和品种
    return nodes.filter(node => node.type === 'crop' || node.type === 'variety');
  } else {
    // 详细模式：显示所有节点
    return nodes;
  }
};

/**
 * 重新渲染图谱
 */
const reRenderGraph = () => {
  console.log('手动重新渲染图谱...');
  if (graphData.value && graphData.value.nodes && graphData.value.nodes.length > 0) {
    renderGraph();
    ElMessage.success('图谱重新渲染完成');
  } else {
    ElMessage.warning('没有可用的图谱数据');
  }
};

/**
 * 调试数据
 */
const debugData = () => {
  console.log('=== 调试信息 ===');
  console.log('graphData.value:', graphData.value);
  console.log('graphData.value.nodes类型:', typeof graphData.value.nodes);
  console.log('graphData.value.nodes是数组吗:', Array.isArray(graphData.value.nodes));
  console.log('节点数量:', graphData.value.nodes ? graphData.value.nodes.length : 0);
  console.log('关系数量:', graphData.value.links ? graphData.value.links.length : 0);
  
  // 详细检查前3个节点和关系的结构
  if (graphData.value.nodes && graphData.value.nodes.length > 0) {
    console.log('前3个节点详细信息:');
    graphData.value.nodes.slice(0, 3).forEach((node, index) => {
      console.log(`节点 ${index + 1}:`, {
        id: node.id,
        name: node.name,
        type: node.type,
        description: node.description
      });
    });
  }
  
  if (graphData.value.links && graphData.value.links.length > 0) {
    console.log('前3个关系详细信息:');
    graphData.value.links.slice(0, 3).forEach((link, index) => {
      console.log(`关系 ${index + 1}:`, {
        source: link.source,
        target: link.target,
        type: link.type,
        label: link.label
      });
    });
  }
  
  // 检查节点ID集合
  if (graphData.value.nodes) {
    const nodeIds = new Set(graphData.value.nodes.map(n => n.id));
    console.log('所有节点ID（前10个）:', Array.from(nodeIds).slice(0, 10));
    
    // 检查关系中是否有无效的节点引用
    if (graphData.value.links) {
      const invalidLinks = graphData.value.links.filter(link => 
        !nodeIds.has(link.source) || !nodeIds.has(link.target)
      );
      console.log('无效关系数量:', invalidLinks.length);
      if (invalidLinks.length > 0) {
        console.log('前5个无效关系:', invalidLinks.slice(0, 5));
      }
    }
  }
  
  console.log('displayNodes:', displayNodes.value);
  console.log('SVG元素:', document.querySelector('#knowledge-graph svg'));
  console.log('==================');
  
  ElMessage.info('调试信息已输出到控制台，请按F12查看');
};

/**
 * 查看品种详情
 */
const viewVarietyDetail = (node) => {
  console.log('查看品种详情:', node);
  ElMessage.info('品种详情功能开发中...');
};

// 拖拽相关函数
const dragstarted = (event, d) => {
  if (!event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
};

const dragged = (event, d) => {
  d.fx = event.x;
  d.fy = event.y;
};

const dragended = (event, d) => {
  if (!event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
};

/**
 * 搜索处理
 */
const handleSearch = async () => {
  if (!searchKeyword.value.trim()) {
    ElMessage.warning('请输入搜索关键词');
    return;
  }
  
  // 如果有选中的建议，使用其节点ID
  if (selectedSuggestion.value && selectedSuggestion.value.name === searchKeyword.value) {
    await handleSearchWithNode(selectedSuggestion.value.id);
    return;
  }
  
  // 否则使用关键词搜索
  searching.value = true;
  try {
    console.log('搜索关键词:', searchKeyword.value);
    const response = await searchGraphNodes(searchKeyword.value);
    console.log('搜索结果:', response);
    
    if (response.code === 200 && response.data && response.data.centerNode) {
      await loadGraphData(response.data.centerNode);
      
      const searchType = response.data.searchType || 'crop';
      if (searchType === 'variety') {
        ElMessage.success(`已找到品种"${response.data.keyword}"并切换到对应的知识图谱`);
      } else {
        ElMessage.success(`已切换到${response.data.keyword}的知识图谱`);
      }
    } else {
      ElMessage.warning(response.msg || '未找到相关节点，请尝试搜索作物名称（如：小麦、玉米）或品种名称');
    }
  } catch (error) {
    console.error('搜索失败:', error);
    ElMessage.error('搜索失败');
  } finally {
    searching.value = false;
  }
};

/**
 * 重建图谱数据
 */
const buildGraph = async () => {
  try {
    await ElMessageBox.confirm(
      '重建图谱数据将会清空现有数据并重新从品种特征中提取，是否继续？',
      '确认操作',
      { type: 'warning' }
    );
    
    building.value = true;
    console.log('开始重建图谱数据...');
    
    const response = await rebuildKnowledgeGraph();
    console.log('重建结果:', response);
    
    if (response.code === 200) {
      ElMessage.success('图谱数据重建成功');
      await initGraph();
    } else {
      ElMessage.error('重建失败：' + response.msg);
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('重建图谱数据失败:', error);
      ElMessage.error('重建图谱数据失败');
    }
  } finally {
    building.value = false;
  }
};

// 生命周期
onMounted(() => {
  console.log('组件已挂载，开始初始化...');
  nextTick(() => {
    initGraph();
  });
});

console.log('知识图谱页面加载完成');
</script>

<style scoped>
.knowledge-graph-container {
  padding: 20px;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f0f2f5;
}

.graph-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: white;
  border-radius: 8px;
  margin-bottom: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.search-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.search-input {
  width: 400px;
}

.suggestion-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 0;
}

.suggestion-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.suggestion-name {
  font-weight: 500;
  color: #333;
}

.suggestion-desc {
  font-size: 12px;
  color: #999;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.graph-legend {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 24px;
  background: white;
  border-radius: 8px;
  margin-bottom: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.legend-left {
  display: flex;
  align-items: center;
  gap: 20px;
}

.legend-center {
  display: flex;
  align-items: center;
  gap: 12px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #666;
}

.legend-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.legend-dot.crop {
  background: #ff7875;
}

.legend-dot.variety {
  background: #40a9ff;
}

.legend-dot.feature {
  background: #52c41a;
}

.legend-help {
  font-size: 12px;
  color: #999;
}

.data-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
}

.stat-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

.stat-label {
  font-size: 14px;
  color: #666;
}

.stat-value {
  font-size: 16px;
  font-weight: bold;
  color: #333;
}

.stat-value.success {
  color: #52c41a;
}

.stat-value.error {
  color: #ff4d4f;
}

.graph-main {
  flex: 1;
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  position: relative;
}

#knowledge-graph {
  width: 100%;
  height: 600px;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  background: #fafafa;
  cursor: grab;
}

#knowledge-graph:active {
  cursor: grabbing;
}

.node-info-panel {
  background: white;
  border: 1px solid #d9d9d9;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  padding: 16px;
  min-width: 200px;
  max-width: 300px;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.panel-header h4 {
  margin: 0;
  color: #333;
  font-size: 14px;
}

.panel-content p {
  margin: 8px 0;
  font-size: 12px;
  color: #666;
  line-height: 1.4;
}

.panel-actions {
  margin-top: 12px;
  display: flex;
  gap: 8px;
}

/* D3.js 相关样式 */
:deep(.links line) {
  stroke: #999;
  stroke-opacity: 0.6;
}

:deep(.nodes circle) {
  cursor: pointer;
  transition: all 0.3s ease;
}

:deep(.nodes circle:hover) {
  stroke-width: 3px;
  filter: brightness(1.1);
}

:deep(.nodes text) {
  pointer-events: none;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
</style>